#include "pch.h"
#include "CppUnitTest.h"
#include <tchar.h>
#include "WaitForTask.h"
#include <tchar.h>

using namespace RSSParser::SQLite;
using namespace NewsReaderDotNet::ViewModels;
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace Windows::System::Threading;
using namespace concurrency;
using namespace Platform;



namespace UnitTests
{
	TEST_CLASS(SQLiteTests)
	{
	private:
		Database^ db;

	public:
		TEST_CLASS_INITIALIZE(InitTestClass)
		{
			RSSParser::Settings::MobilitySettings::Uri = "https://readability.com/api/content/v1/parser?token=1eced84b6c4c07896c3c2140887b34acbe10af25&url=";
			RSSParser::Settings::MobilitySettings::UserAgent = "Win8NewsReader - 88c1a20e-136c-4e19-9e84-971549ad74d2";
			RSSParser::Settings::MobilitySettings::Name = "Mobility";
		}
		TEST_METHOD_INITIALIZE(PrepareSQLiteTests)
		{
			CreateDB();
		}

		TEST_METHOD_CLEANUP(CloseDB)
		{
			db = nullptr;
		}

		TEST_METHOD(EnsureThatTableIsThere)
		{
			auto stmt =  db->PrepareStatement("SELECT * FROM sqlite_master where type = \"table\" and name = \"feed_items\"");
			Assert::IsTrue(stmt->HasMore());
		}

		TEST_METHOD(MakeSureDataIsThere)
		{
			auto stmt = db->PrepareStatement("INSERT INTO feed_items (feed_id, uri, text) values (1, \"http://test.com\", \"Hello World\")");
			stmt->Execute();

			stmt = db->PrepareStatement("SELECT * FROM feed_items");

			Assert::IsTrue(stmt->HasMore());
			Assert::IsTrue(stmt->ColumnAsIntAt(0) > 0);
			Assert::AreEqual(1, stmt->ColumnAsIntAt(1));
			Assert::AreEqual("http://test.com", stmt->ColumnAsTextAt(2));
			Assert::AreEqual("Hello World", stmt->ColumnAsTextAt(3));
		}

		TEST_METHOD(SaveFeedToDB)
		{
			auto t = create_task([this]()-> void
			{
				auto fi = ref new FeedInfo("http://news.yahoo.com/rss/");
				fi->Load();

				auto stmt = db->PrepareStatement("INSERT INTO feeds (uri) values (\"" + fi->Uri->AbsoluteUri + "\")");
				stmt->Execute();

				stmt = db->PrepareStatement("SELECT last_insert_rowid()");
				Assert::IsTrue(stmt->HasMore());
				int feedId = stmt->ColumnAsIntAt(0);

				for each(auto feedItem in fi->FeedItems)
				{
					stmt = db->PrepareStatement("INSERT INTO feed_items (feed_id, uri, text) values (?, ?, ?)");
					stmt->BindInt(1, feedId);
					stmt->BindText(2, feedItem->Link->AbsoluteUri);
					stmt->BindText(3, feedItem->FullText);
					stmt->Execute();
				}

				stmt = db->PrepareStatement("SELECT * FROM feed_items");
				Assert::IsTrue(stmt->HasMore());
				Assert::IsTrue(stmt->ColumnAsIntAt(0) > 0);
				Assert::AreEqual(1, stmt->ColumnAsIntAt(1));
			});

			bool success;
			WaitForTask(t, success, 100000);
			Assert::IsTrue(success, _T("Operation timed-out."));

		}

	private:
		void CreateDB()
		{
			auto path = ref new String(_T("sqlite.test"));
			db = ref new Database(path, true);
			Assert::IsTrue(db->Ready);

			auto stmt = db->PrepareStatement("CREATE TABLE \"feed_items\" (\"id\" INTEGER PRIMARY KEY  AUTOINCREMENT  NOT NULL , \"feed_id\" INTEGER NOT NULL , \"uri\" TEXT NOT NULL , \"text\" TEXT)");
			if(!stmt->Valid)
			{
				stmt = db->PrepareStatement("DELETE TABLE feed_items");
				stmt->Execute();
			}
			else
			{
				stmt->Execute();
			}

			stmt = db->PrepareStatement("CREATE TABLE \"feeds\" (\"id\" INTEGER PRIMARY KEY  AUTOINCREMENT  NOT NULL ,  \"uri\" TEXT NOT NULL)");
			if(!stmt->Valid)
			{
				stmt = db->PrepareStatement("DELETE TABLE feeds");
				stmt->Execute();
			}
			else
			{
				stmt->Execute();
			}
		}
	};
}